


/**
 * 对象里是否有属性,通常用于判断将object{}当作键值对来使用的场景
 * @date 2022/3/31 - 下午4:45:24
 *
 * @export
 * @param {*} object
 * @returns {boolean}
 */
export function hasProperty(object: any): boolean {
    if (!object) return false;
    for (let key in object) {
        return true;
    }
    return false;
}


/**
 * 异步延时
 * @date 2022/5/10 - 10:45:52
 *
 * @export
 * @async
 * @param {number} ms
 * @returns {Promise<void>}
 */
export async function delay(ms: number): Promise<void> {
    return new Promise((resolve) => {
        setTimeout(resolve, ms)
    });
}



/**
 * 提取数组中最符合条件的元素 O(n)
 * @date 2022/5/10 - 20:57:23
 *
 * @export
 * @template T
 * @param {T[]} arr
 * @param {(winner: T, next: T) => T} compareFn 数组中每个元素对比，返回最符合条件的元素
 * @param {(item: T) => boolean} filter 先筛选,通过筛选的元素再进行提取最符合的
 * @returns {(T | undefined)}
 */
export function arrWinner<T>(arr: Iterable<T>, compareFn: (winner: T, next: T) => T, filter?: (item: T) => boolean): T | null {
    let winner: T | null = null;
    for (let item of arr) {
        if (filter?.call(null, item) === false) continue;
        if (!winner) {
            winner = item;
            continue;
        }
        winner = compareFn(winner, item);
    }
    return winner;
}


/**
 * 原数组直接删除符合条件的元素，返回删除的数量
 * @date 2022/5/12 - 15:58:04
 *
 * @export
 * @template T
 * @param {Array<T>} arr
 * @param {(item: T) => boolean} itemCanRemove
 * @returns {number}
 */
export function arrRemoveItems<T>(arr: Array<T>, itemCanRemove: (item: T) => boolean): number {
    let deleteCount = 0;
    for (let i = 0; i < arr.length; i++) {
        if (itemCanRemove(arr[i])) {
            arr.splice(i, 1);
            i--;
            deleteCount++;
            continue;
        }
    }
    return deleteCount;
}


/**
 * 分组
 * @date 2022/5/24 - 17:51:56
 *
 * @export
 * @template Item
 * @param {Item[]} arr
 * @param {(v: Item) => GroupBy} grouper
 * @returns {Map<GroupBy, Item[]>}
 */
export function arrGroup<Item, GroupBy>(arr: Item[], grouper: (v: Item) => GroupBy): Map<GroupBy, Item[]> {
    let groups: Map<GroupBy, Item[]> = new Map<GroupBy, Item[]>();

    for (let item of arr) {
        let key = grouper(item);
        let list = groups.get(key);
        if (!list) {
            list = [];
            groups.set(key, list);
        }
        list.push(item);
    }

    return groups;

}


/**
 * 数组元素值累加
 * @date 2022/5/24 - 18:01:32
 *
 * @export
 * @template Item
 * @param {Item[]} arr
 * @param {(item: Item) => number} mapper
 * @returns {number}
 */
export function arrSum<Item>(arr: Item[], mapper: (item: Item) => number): number {
    let sum = 0;
    for (let item of arr) {
        sum += mapper(item);
    }
    return sum;
}


interface Type<T> extends Function {
    new(...args: any[]): T;
}
/**
 * 解析进程入口参数为一个对象, 格式为 -配置名1=配置值1 -配置名2="带有空格 的配置值", 转为 {配置名1:"配置值1",配置名2:"带有空格 的配置值"}
 * @date 2022/5/25 - 22:27:49
 *
 * @export
 * @template Option
 * @param {string[]} configNames 配置名列表
 * @param {string[]} args 进程传入参数列表
 * @param {string} [configNamePrefix='-']
 */
export function parseProcessArgv(configNames: string[], args: string[], configNamePrefix: string = '-'): { [configName: string]: string } {
    let setOption: { [configName: string]: string } = {};
    for (let arg of args) {
        let argStr = arg.trim();
        for (let cfgName of configNames) {
            let st = configNamePrefix + cfgName + '=';
            if (argStr.startsWith(st)) {
                let val = argStr.substring(st.length);
                //支持值头尾有双引号
                val = val.replace(/^"?(.*?)"?$/ig, ($0, $1) => $1);
                setOption[cfgName] = val;
            }
        }
    }
    return setOption;
}